#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include "lexer.h"

// 创建词法分析器
// 参数：
// - input: 要分析的输入字符串
// 返回值：创建的词法分析器指针，失败返回NULL
Lexer* create_lexer(const char* input) {
    if (!input) {
        return NULL;
    }
    
    Lexer* lexer = (Lexer*)malloc(sizeof(Lexer));
    if (!lexer) {
        return NULL;
    }
    
    lexer->input = input;
    lexer->position = 0;
    lexer->read_position = 0;
    lexer->line = 1;
    lexer->column = 1;
    lexer->current_char = input[0];
    
    return lexer;
}

// 释放词法分析器资源
// 参数：
// - lexer: 要释放的词法分析器指针
void free_lexer(Lexer* lexer) {
    if (lexer) {
        free(lexer);
    }
}

// 读取下一个字符并更新词法分析器状态
static void read_char(Lexer* lexer) {
    if (!lexer) {
        return;
    }
    
    if (lexer->read_position >= (int)strlen(lexer->input)) {
        lexer->current_char = '\0';
    } else {
        lexer->current_char = lexer->input[lexer->read_position];
    }
    
    lexer->position = lexer->read_position;
    lexer->read_position++;
    
    // 更新行号和列号
    if (lexer->current_char == '\n') {
        lexer->line++;
        lexer->column = 1;
    } else if (lexer->current_char == '\t') {
        // 制表符通常跳到下一个制表位（假设制表位为8个字符）
        lexer->column = ((lexer->column + 7) / 8) * 8 + 1;
    } else if (lexer->current_char != '\0') {
        lexer->column++;
    }
}

void skip_whitespace(Lexer* lexer) {
    if (!lexer) {
        return;
    }
    
    while (lexer->current_char == ' ' || lexer->current_char == '\t' || 
           lexer->current_char == '\n' || lexer->current_char == '\r') {
        read_char(lexer);
    }
}

Token* read_identifier(Lexer* lexer) {
    if (!lexer) {
        return create_token(ERROR, "Invalid lexer", 0, 0);
    }
    
    int start_pos = lexer->position;
    int start_line = lexer->line;
    int start_col = lexer->column;
    
    while (isalpha(lexer->current_char) || lexer->current_char == '_' || isdigit(lexer->current_char)) {
        read_char(lexer);
    }
    
    int len = lexer->position - start_pos;
    char* identifier = (char*)malloc(len + 1);
    if (!identifier) {
        return create_token(ERROR, "Memory allocation failed", start_line, start_col);
    }
    
    strncpy(identifier, lexer->input + start_pos, len);
    identifier[len] = '\0';
    
    TokenType type = check_keyword(identifier);
    Token* token = create_token(type, identifier, start_line, start_col);
    
    free(identifier);
    return token;
}

// 读取数字（支持整数和浮点数）
Token* read_number(Lexer* lexer) {
    if (!lexer) {
        return create_token(ERROR, "Invalid lexer", 0, 0);
    }
    
    int start_pos = lexer->position;
    int start_line = lexer->line;
    int start_col = lexer->column;
    
    // 读取整数部分
    while (isdigit(lexer->current_char)) {
        read_char(lexer);
    }
    
    // 检查是否有小数部分
    if (lexer->current_char == '.') {
        read_char(lexer);  // 跳过小数点
        
        // 读取小数部分
        while (isdigit(lexer->current_char)) {
            read_char(lexer);
        }
    }
    
    int len = lexer->position - start_pos;
    if (len <= 0) {
        return create_token(ERROR, "Invalid number format", start_line, start_col);
    }
    
    char* number = (char*)malloc(len + 1);
    if (!number) {
        return create_token(ERROR, "Memory allocation failed", start_line, start_col);
    }
    
    strncpy(number, lexer->input + start_pos, len);
    number[len] = '\0';
    
    Token* token = create_token(NUMBER, number, start_line, start_col);
    
    free(number);
    return token;
}

// 读取字符串
Token* read_string(Lexer* lexer) {
    if (!lexer) {
        return create_token(ERROR, "Invalid lexer", 0, 0);
    }
    
    int start_line = lexer->line;
    int start_col = lexer->column;
    
    // 初始化一个动态缓冲区
    int buffer_size = 64;
    char* buffer = (char*)malloc(buffer_size + 1);
    if (!buffer) {
        return create_token(ERROR, "Memory allocation failed", start_line, start_col);
    }
    
    int content_length = 0;
    
    // 跳过开始引号
    read_char(lexer);
    
    // 读取字符串内容直到遇到结束引号或文件结束
    while (lexer->current_char != '\'' && lexer->current_char != '\0') {
        // 检查缓冲区是否需要扩容
        if (content_length >= buffer_size) {
            buffer_size *= 2;
            char* new_buffer = (char*)realloc(buffer, buffer_size + 1);
            if (!new_buffer) {
                free(buffer);
                return create_token(ERROR, "Memory reallocation failed", start_line, start_col);
            }
            buffer = new_buffer;
        }
        
        // 处理转义字符
        if (lexer->current_char == '\\') {
            read_char(lexer); // 跳过反斜杠
            if (lexer->current_char == '\0') {
                free(buffer);
                return create_token(ERROR, "Unclosed string", start_line, start_col);
            }
            
            // 根据转义字符添加相应的字符
            switch (lexer->current_char) {
                case 'n': buffer[content_length++] = '\n'; break;
                case 't': buffer[content_length++] = '\t'; break;
                case 'r': buffer[content_length++] = '\r'; break;
                case '\'': buffer[content_length++] = '\''; break;
                case '\\': buffer[content_length++] = '\\'; break;
                default: 
                    // 未知转义序列，保留反斜杠和字符
                    buffer[content_length++] = '\\';
                    buffer[content_length++] = lexer->current_char;
                    break;
            }
        } else {
            // 普通字符直接添加
            buffer[content_length++] = lexer->current_char;
        }
        
        read_char(lexer);
    }
    
    // 检查是否遇到文件结束而不是结束引号
    if (lexer->current_char == '\0') {
        free(buffer);
        return create_token(ERROR, "Unclosed string", start_line, start_col);
    }
    
    // 添加字符串结束符
    buffer[content_length] = '\0';
    
    // 跳过结束引号
    read_char(lexer);
    
    // 创建字符串token
    Token* token = create_token(STRING, buffer, start_line, start_col);
    
    // 释放缓冲区
    free(buffer);
    
    return token;
}

// 获取下一个Token
Token* get_next_token(Lexer* lexer) {
    if (!lexer) {
        return create_token(ERROR, "Invalid lexer", 0, 0);
    }
    
    skip_whitespace(lexer);
    
    if (lexer->current_char == '\0') {
        return create_token(EOF_TOKEN, "", lexer->line, lexer->column);
    }
    
    Token* token;
    switch (lexer->current_char) {
        case '=':
            token = create_token(EQUAL, "=", lexer->line, lexer->column);
            read_char(lexer);
            break;
        case '<':
            read_char(lexer);
            if (lexer->current_char == '>') {
                token = create_token(NOT_EQUAL, "<>", lexer->line, lexer->column);
                read_char(lexer);
            } else if (lexer->current_char == '=') {
                token = create_token(LESS_EQUAL, "<=", lexer->line, lexer->column);
                read_char(lexer);
            } else {
                token = create_token(LESS, "<", lexer->line, lexer->column);
            }
            break;
        case '>':
            read_char(lexer);
            if (lexer->current_char == '=') {
                token = create_token(GREATER_EQUAL, ">=", lexer->line, lexer->column);
                read_char(lexer);
            } else {
                token = create_token(GREATER, ">", lexer->line, lexer->column);
            }
            break;
        case '+':
            token = create_token(PLUS, "+", lexer->line, lexer->column);
            read_char(lexer);
            break;
        case '-':
            if (lexer->read_position < (int)strlen(lexer->input) && lexer->input[lexer->read_position] == '-') {
                skip_comment(lexer);
                return get_next_token(lexer);
            } else {
                token = create_token(MINUS, "-", lexer->line, lexer->column);
                read_char(lexer);
            }
            break;
        case '*':
            token = create_token(MULTIPLY, "*", lexer->line, lexer->column);
            read_char(lexer);
            break;
        case '/':
            token = create_token(DIVIDE, "/", lexer->line, lexer->column);
            read_char(lexer);
            break;
        case '(':
            token = create_token(LEFT_PAREN, "(", lexer->line, lexer->column);
            read_char(lexer);
            break;
        case ')':
            token = create_token(RIGHT_PAREN, ")", lexer->line, lexer->column);
            read_char(lexer);
            break;
        case ',':
            token = create_token(COMMA, ",", lexer->line, lexer->column);
            read_char(lexer);
            break;
        case ';':
            token = create_token(SEMICOLON, ";", lexer->line, lexer->column);
            read_char(lexer);
            break;
        case '.':
            // 检查小数点后面是否有数字，如果有，则作为浮点数的一部分处理
            if (lexer->read_position < (int)strlen(lexer->input) && isdigit(lexer->input[lexer->read_position])) {
                return read_number(lexer);
            } else {
                token = create_token(DOT, ".", lexer->line, lexer->column);
                read_char(lexer);
            }
            break;
        case '\'':
            return read_string(lexer);
        default:
            if (isalpha(lexer->current_char) || lexer->current_char == '_') {
                return read_identifier(lexer);
            } else if (isdigit(lexer->current_char)) {
                return read_number(lexer);
            } else {
                char error_char[2] = {lexer->current_char, '\0'};
                token = create_token(ERROR, error_char, lexer->line, lexer->column);
                read_char(lexer);
            }
    }
    
    return token;
}

// 判断是否为关键字
TokenType check_keyword(const char* identifier) {
    if (!identifier) {
        return IDENTIFIER;
    }
    
    if (strcmp(identifier, "SELECT") == 0) return SELECT;
    if (strcmp(identifier, "FROM") == 0) return FROM;
    if (strcmp(identifier, "WHERE") == 0) return WHERE;
    if (strcmp(identifier, "CREATE") == 0) return CREATE;
    if (strcmp(identifier, "TABLE") == 0) return TABLE;
    if (strcmp(identifier, "INSERT") == 0) return INSERT;
    if (strcmp(identifier, "INTO") == 0) return INTO;
    if (strcmp(identifier, "VALUES") == 0) return VALUES;
    if (strcmp(identifier, "DELETE") == 0) return DELETE;
    if (strcmp(identifier, "IF") == 0) return IF;
    if (strcmp(identifier, "EXISTS") == 0) return EXISTS;
    if (strcmp(identifier, "NOT") == 0) return NOT;
    if (strcmp(identifier, "DROP") == 0) return DROP;
    if (strcmp(identifier, "ALTER") == 0) return ALTER;
    if (strcmp(identifier, "SET") == 0) return SET;
    if (strcmp(identifier, "UPDATE") == 0) return UPDATE;
    if (strcmp(identifier, "ADD") == 0) return ADD;
    if (strcmp(identifier, "MODIFY") == 0) return MODIFY;
    if (strcmp(identifier, "COLUMN") == 0) return COLUMN;
    if (strcmp(identifier, "INT") == 0) return INT;
    if (strcmp(identifier, "VARCHAR") == 0) return VARCHAR;
    if (strcmp(identifier, "FLOAT") == 0) return FLOAT;
    if (strcmp(identifier, "DOUBLE") == 0) return DOUBLE;
    
    return IDENTIFIER;
}

// 跳过注释
void skip_comment(Lexer* lexer) {
    if (!lexer) {
        return;
    }
    
    // 已经读取了第一个'-'
    read_char(lexer); // 读取第二个'-'
    
    // 跳过可选的空格
    if (lexer->current_char == ' ') {
        read_char(lexer);
    }
    
    // 跳过注释内容，直到遇到换行符或文件结束
    while (lexer->current_char != '\n' && lexer->current_char != '\0') {
        read_char(lexer);
    }
    
    // 如果遇到换行符，读取它以更新行号和列号
    if (lexer->current_char == '\n') {
        read_char(lexer);
    }
}